package com.gitee.apanlh.util.tree;

import com.gitee.apanlh.annotation.tree.TreeId;
import com.gitee.apanlh.annotation.tree.TreeParentId;
import com.gitee.apanlh.util.base.CollUtils;
import com.gitee.apanlh.util.base.Empty;
import com.gitee.apanlh.util.base.Eq;
import com.gitee.apanlh.util.base.IteratorUtils;
import com.gitee.apanlh.util.reflection.ClassUtils;
import com.gitee.apanlh.util.reflection.ReflectionUtils;
import com.gitee.apanlh.util.valid.ValidParam;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

/**
 * 	树工具类
 *
 * 	@author Pan
 */
public class TreeUtils {

	/**
	 * 	构造函数
	 *
	 * 	@author Pan
	 */
	private TreeUtils() {
		//	不允许外部实例
		super();
	}

	/**
	 * 	创建数结构
	 * 	<br>无排序
	 *	<br>无限深度
	 *
	 * 	@author Pan
	 * 	@param	<T>		数据类型
	 * 	@param 	list	集合
	 * 	@return	List
	 */
	public static <T> List<Map<String, Object>> create(List<T> list) {
		return create(list, -1, false);
	}

	/**
	 * 	创建数结构
	 * 	<br>自定会排序
	 *	<br>无限深度
	 *
	 * 	@author Pan
	 * 	@param	<T>		数据类型
	 * 	@param 	list	集合
	 * 	@param 	isOrder	true排序(升序)
	 * 	@return	List
	 */
	public static <T> List<Map<String, Object>> create(List<T> list, boolean isOrder) {
		return create(list, -1, isOrder);
	}

	/**
	 * 	创建树结构
	 * 	<br>自定义排序
	 *	<br>自定义深度层级,0或负数则代表无限深度
	 *
	 * 	@author Pan
	 * 	@param	<T>			数据类型
	 * 	@param 	list		集合
	 * 	@param 	deep		层级
	 * 	@param 	isOrder		true排序(升序)
	 * 	@return	List
	 */
	public static <T> List<Map<String, Object>> create(List<T> list, int deep, boolean isOrder) {
		if (ValidParam.isEmpty(list)) {
			return Empty.list();
		}

		Class<?> clazz = ClassUtils.getClass(list);
		if (!TreeScan.getTreeAnnotation(clazz) || !TreeScan.getTreeIdAnnotation(clazz)) {
			return Empty.list();
		}

		//	找到相对应注解
		List<Field> findAnnotationList = ReflectionUtils.getFieldAnnotation(clazz, TreeId.class, TreeParentId.class);
		if (ValidParam.isEmpty(findAnnotationList)) {
			return Empty.list();
		}

		//	属别名
		String treeIdAlias = null;
		//	关联父级ID名称
		String treeParentName = null;

		//	排序
		for (int i = 0, len = findAnnotationList.size(); i < len; i++) {
			Field field = findAnnotationList.get(i);
			if (ReflectionUtils.scanFieldAnnotation(field, TreeId.class)) {
				treeIdAlias = TreeScan.getAlias(field);
				if (isOrder) {
					CollUtils.sortNumber(list, field.getName());
				}
			} else {
				treeParentName = field.getName();
			}
		}

		//	0或负数则代表无限深度
		if (deep <= 0) {
			deep = -1;
		}
		return forTree(list, findAnnotationList, treeParentName, treeIdAlias, deep);
	}

	/**
	 * 	遍历树
	 *
	 * 	@author Pan
	 * 	@param 	list				数据集合
	 * 	@param 	findAnnotationList	注解集合
	 * 	@param	treeParentName		父类别名
	 * 	@param 	treeIdAlias			父类id别名
	 * 	@param 	deep				递归深度
	 * 	@return	List
	 */
	private static <T> List<Map<String, Object>> forTree(List<T> list, List<Field> findAnnotationList, String treeParentName, String treeIdAlias, int deep) {
		List<Map<String, Object>> listDynamicTree = CollUtils.newArrayList(list.size());

		IteratorUtils.array(list, t -> {
			//	获取父级Id值
			String parentIdValue = String.valueOf(TreeProperties.getIdValueByAnnotation(t, findAnnotationList, TreeParentId.class));
			String idValue = String.valueOf(TreeProperties.getIdValueByAnnotation(t, findAnnotationList, TreeId.class));

			//	根据一级菜单搜索子集值
			if (ValidParam.isEmpty(parentIdValue) || Eq.str(idValue, parentIdValue) || "0".equals(parentIdValue)) {
				//	设置树值
				Map<String, Object> dynamicTree = TreeProperties.setTreeValue(t, listDynamicTree);
				//	获取主Id值
				Object id = TreeProperties.getIdValueByAnnotation(t, findAnnotationList, TreeId.class);
				//	找寻子类
				findChildren(list, dynamicTree, id, treeParentName, treeIdAlias, deep, 1);
			}
		});
		return listDynamicTree;
	}

	/**
	 * 	寻找子集
	 *
	 * 	@author Pan
	 * 	@param 	list			数据集合
	 * 	@param 	dynamicTree		动态树
	 * 	@param 	id				id
	 * 	@param 	parentIdName	父id
	 * 	@param 	treeIdAlias		父id别名
	 * 	@param 	deep			递归深度
	 */
	private static <T> void findChildren(List<T> list, Map<String, Object> dynamicTree, Object id, String parentIdName, String treeIdAlias, int deep, int nowDeep) {
		if (nowDeep == deep) {
			return ;
		}

		List<T> find = CollUtils.find(list, t -> {
			String idStr = String.valueOf(id);
			String pidStr = String.valueOf(ReflectionUtils.getFieldValue(t, parentIdName));
			return Eq.str(idStr, pidStr);
		});

		//	找到关联的子集并添加
		List<Map<String, Object>> listChildrenTree = TreeProperties.setTreeChildrenValue(find, dynamicTree);
		if (ValidParam.isNotEmpty(listChildrenTree)) {
			nowDeep ++;
		}

		//	无子集则跳过
		final int finalNowDeep = nowDeep;
		IteratorUtils.collection(listChildrenTree, (childrenTree, iterator) ->
			//	递归子集
			findChildren(list, childrenTree, childrenTree.get(treeIdAlias), parentIdName, treeIdAlias, deep, finalNowDeep)
		);
	}
}
